var express = require('express');
var Excel = require("exceljs");
var router = express.Router();
const Relation = require('../models/Relation');
const RelationInstance = require('../models/RelationInstance');
const RelationType = require('../models/RelationType');
const SchemaDef = require('../models/SchemaDef');
const Instance = require('../models/Instance');
var tools = require('../utils/tools')
var fs = require('fs');
var os = require('os');
var path = require("path");
var settings = require('../settings')

/**
 * @swagger
 *
 * /cmdb/relations/page:
 *   get:
 *     tags:
 *       - 关系管理
 *     summary: 分页查询关系
 *     description: 支持标准方式查询。$_foo=bar
 *     responses:
 *       200:
 *         description: 返回标准分页结构
 */
router.get('/page', function (req, res, next) {
  Relation.page(tools.queryResolver(req.query), req.query.page, req.query.size, result => {
    return res.json({ status: 'success', data: result.docs, pageable: result.pageable })
  })
});

/**
 * @swagger
 *
 * /cmdb/relations/list:
 *   get:
 *     tags:
 *       - 关系管理
 *     summary: 查询所有关系
 *     description: 查询所有关系
 *     responses:
 *       200:
 *         description: 查询所有关系
 */
router.get('/list', async function (req, res, next) {
  var docs = await Relation.find(tools.queryResolver(req.query))
    .populate('type')
    .populate('src')
    .populate('dest')
  return res.json({ status: 'success', data: docs })
});

/**
 * @swagger
 *
 * /cmdb/relations/list/simple:
 *   get:
 *     tags:
 *       - 关系管理
 *     summary: 查询所有关系简单结构
 *     description: 查询所有关系简单结构
 *     responses:
 *       200:
 *         description: 查询所有关系简单结构
 */
router.get('/list/simple', async function (req, res, next) {
  var docs = await Relation.find(tools.queryResolver(req.query), {_id: 1, desc: 1})
  return res.json({ status: 'success', data: docs })
});

router.get('/:id', function (req, res, next) {
  Relation.findOne({ _id: req.params.id })
    .populate('type')
    .populate('src')
    .populate('dest')
    .exec((err, doc) => {
      if (err) res.json({ status: 'failure' });
      res.json({ status: 'success', data: doc })
    })
});

router.put('/:id', async function (req, res, next) {
  var { type, src, dest, desc, restrain, attrs } = req.body

  var count = await RelationInstance.count({ rela: req.params.id })
  if (count > 0) {
    return tools.handleError(res, '关系实例已存在，无法完成更新');
  }
  var typeInst = await RelationType.findById(tools.isObject(type) ? type._id : type)
  var srcInst = await SchemaDef.findById(tools.isObject(src) ? src._id : src)
  var destInst = await SchemaDef.findById(tools.isObject(dest) ? dest._id : dest)

  if (!typeInst || !srcInst || !destInst) {
    return tools.handleError(res, '关系类型，源模型或目标模型不存在，无法完成更新');
  }

  var data = {
    type: typeInst._id,
    src: srcInst._id,
    dest: destInst._id,
    attrs,
    restrain,
    desc
  }

  Relation.findByIdAndUpdate(req.params.id, { $set: data }, { new: false }, function (err, doc) {
    if (err) return tools.handleError(res, err);
    res.json({ status: 'success', data: doc })
  });
});

router.delete('/:id', function (req, res, next) {
  Relation.findByIdAndDelete(req.params.id, function (err, doc) {
    if (err) return tools.handleError(res, err);
    res.json({ status: 'success', data: doc })
  });
});

router.post('/', function (req, res, next) {
  Relation.create(req.body, function (err, doc) {
    if (err) return tools.handleError(res, err);
    res.json({ status: 'success', data: doc })
  });
});

/**
 * 下载关系实例导入模板
 */
router.get('/:id/tpl', async function (req, res, next) {
  var mRelation = await Relation.findById(req.params.id)
  var allAttrs = [...mRelation.attrs]
  var workbook = new Excel.Workbook();

  var mSheet = workbook.addWorksheet('template');
  var columns = [{ header: '源实例', key: 'src', width: 24 }, { header: '目标实例', key: 'dest', width: 24 },{ header: '描述', key: 'desc', width: 24 }]

  // 定义列
  allAttrs.forEach(attr => {
    columns.push({ header: attr.name, key: attr.field, width: 16 })
  })


  mSheet.columns = columns;
  // 表头添加样式
  mSheet.getRow(1).alignment = { vertical: 'middle', horizontal: 'center' }
  mSheet.getRow(1).font = { bold: true }

  var helpSheet = workbook.addWorksheet('help')
  helpSheet.state = 'hidden'
  let helpSheetColSeq = 1

  var srcAvailableInsts = await Instance.find({schemadef: mRelation.src})
  var destAvailableInsts = await Instance.find({schemadef: mRelation.dest})

  if (srcAvailableInsts.length > 0) {
    var values = srcAvailableInsts.map(it => it.code + '$$' + it.name)
    helpSheet.getColumn(1).values = values
    var helpSheetColLetter = 'A'
    var formulae = ['help!$' + helpSheetColLetter + '$1:$' + helpSheetColLetter + '$' + values.length]

    var col = mSheet.getColumn('src')
    for (var j = 0; j < 65536; j++) {
      mSheet.getCell(j + 2, col._number).dataValidation = {
        type: 'list',
        allowBlank: true,
        formulae: formulae
      }
    }
  }

  if (destAvailableInsts.length > 0) {
    var values = destAvailableInsts.map(it => it.code + '$$' + it.name)
    helpSheet.getColumn(2).values = values
    var helpSheetColLetter = 'B'
    var formulae = ['help!$' + helpSheetColLetter + '$1:$' + helpSheetColLetter + '$' + values.length]

    var col = mSheet.getColumn('dest')
    for (var j = 0; j < 65536; j++) {
      mSheet.getCell(j + 2, col._number).dataValidation = {
        type: 'list',
        allowBlank: true,
        formulae: formulae
      }
    }
  }

  var tmpDir = settings.TMP_PATH ? settings.TMP_PATH : os.tmpdir()
  var fileName = mRelation.desc + '关系实例导入模板.xlsx'
  fileName = encodeURI(fileName, "GBK")
  fileName = fileName.toString('iso8859-1')
  var tmpFile = path.join(tmpDir, req.params.id + '.xlsx')
  await workbook.xlsx.writeFile(tmpFile);

  res.set({
    "Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    "Content-Disposition": "attachment; filename=" + fileName,
    "Access-Control-Expose-Headers": "Content-Disposition"
  });
  fs.createReadStream(tmpFile).pipe(res);
});

module.exports = router;
